<!DOCTYPE HTML>
<html lang="zh-CN">

<head>
    <!--Setting-->
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <meta http-equiv="Cache-Control" content="no-siteapp">
    <meta http-equiv="Cache-Control" content="no-transform">
    <meta name="renderer" content="webkit|ie-comp|ie-stand">
    <meta name="apple-mobile-web-app-capable" content="涛哥的博客">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="format-detection" content="telephone=no,email=no,adress=no">
    <meta name="browsermode" content="application">
    <meta name="screen-orientation" content="portrait">
    <meta name="theme-version" content="1.2.3">
    <meta name="root" content="/">
    <link rel="dns-prefetch" href="https://jaredtao.github.io">
    <!--SEO-->

<meta name="keywords" content="Qt,Qml,QtQuick,组件化编程" />


<meta name="description" content="
简介
源码
效果预览
Qt本身的国际化
存在翻译不全的问题
新的方案
关于批量翻译
总结

简介本文是《玩转Qml》系列文章的第十二篇，主要讨论多国语言动态翻译。
之前分享过使用Qt自带翻译的..." />


<meta name="robots" content="all" />
<meta name="google" content="all" />
<meta name="googlebot" content="all" />
<meta name="verify" content="all" />
    <!--Title-->

<title>
    
    玩转Qml(12)-再谈动态国际化 |
    
    涛哥的博客
</title>

<link rel="alternate" href="/atom.xml" title="涛哥的博客" type="application/atom+xml">


<link rel="icon" href="/favicon.ico">

    


<link rel="stylesheet" href="/css/bootstrap.min.css?rev=3.3.7.css">
<link rel="stylesheet" href="/css/font-awesome.min.css?rev=4.7.0.css">
<link rel="stylesheet" href="/css/style.css?rev=@@hash.css">

    
<div class="hide">
    <script type="text/javascript">
    var cnzz_protocol = (("https:" == document.location.protocol) ? " https://" : " http://");
    document.write(unescape("%3Cspan class='cnzz_stat_icon_1263868967 hide' %3E%3Cscript%20src%3D%22https%3A%2F%2Fs95.cnzz.com%2Fz_stat.php%3Fweb_id%3D1272564536%22%3E%3C%2Fscript%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "s19.cnzz.com/z_stat.php%3Fid%3D1263868967%26show%3Dpic1' type='text/javascript'%3E%3C/script%3E"));
    </script>
</div>




    

<script>
(function() {
    var bp = document.createElement('script');
    var curProtocol = window.location.protocol.split(':')[0];
    if (curProtocol === 'https') {
        bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
    } else {
        bp.src = 'http://push.zhanzhang.baidu.com/push.js';
    }
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(bp, s);
})();
</script>

<meta name="generator" content="Hexo 4.2.1"></head>
<!--[if lte IE 8]>
<style>
    html{ font-size: 1em }
</style>
<![endif]-->
<!--[if lte IE 9]>
<div style="ie">你使用的浏览器版本过低，为了你更好的阅读体验，请更新浏览器的版本或者使用其他现代浏览器，比如Chrome、Firefox、Safari等。</div>
<![endif]-->
<body>
    <header class="main-header"  style="background-image:url(
    http://snippet.shenliyang.com/img/banner.jpg)"
     >
    <div class="main-header-box">
        <a class="header-avatar" href="/" title='JaredTao'>
            <img src="/img/avatar.jpg" alt="logo头像" class="img-responsive center-block">
        </a>
        <div class="branding">
            <!--<h2 class="text-hide">Snippet主题,从未如此简单有趣</h2>-->
            
            <h2>
                单枪匹马亦对饮，历经磨难记初心
            </h2>
            
        </div>
    </div>
</header>
    <nav class="main-navigation">
    <div class="container">
        <div class="row">
            <div class="col-sm-12">
                <div class="navbar-header"><span class="nav-toggle-button collapsed pull-right" data-toggle="collapse" data-target="#main-menu" id="mnav">
                        <span class="sr-only"></span>
                        <i class="fa fa-bars"></i>
                    </span>
                    <a class="navbar-brand" href="https://jaredtao.github.io">
                        涛哥的博客</a>
                </div>
                <div class="collapse navbar-collapse" id="main-menu">
                    <ul class="menu">
                        
                        <li role="presentation" class="text-center">
                            <a href="/"><i class="fa "></i>
                                首页</a>
                        </li>
                        
                        <li role="presentation" class="text-center">
                            <a href="/categories/玩转Qt/"><i class="fa "></i>
                                玩转Qt</a>
                        </li>
                        
                        <li role="presentation" class="text-center">
                            <a href="/categories/玩转Qml/"><i class="fa "></i>
                                玩转Qml</a>
                        </li>
                        
                        <li role="presentation" class="text-center">
                            <a href="/categories/玩转QtQuick/"><i class="fa "></i>
                                玩转QtQuick</a>
                        </li>
                        
                        <li role="presentation" class="text-center">
                            <a href="/categories/涛哥的博客/"><i class="fa "></i>
                                涛哥的博客</a>
                        </li>
                        
                        <li role="presentation" class="text-center">
                            <a href="/archives/"><i class="fa "></i>
                                时间轴</a>
                        </li>
                        
                    </ul>
                </div>
            </div>
        </div>
    </div>
</nav>
    <section class="content-wrap">
        <div class="container">
            <div class="row">
                <main class="col-md-8 main-content m-post">
                    <p id="process"></p>
<article class="post">
    <div class="post-head">
        <h1 id="玩转Qml(12)-再谈动态国际化">
            
            玩转Qml(12)-再谈动态国际化
            
        </h1>
        <div class="post-meta">
    
    <span class="categories-meta fa-wrap">
        <i class="fa fa-folder-open-o"></i>
        <a class="category-link" href="/categories/%E7%8E%A9%E8%BD%ACQml/">玩转Qml</a>
    </span>
    
    
    <span class="fa-wrap">
        <i class="fa fa-tags"></i>
        <span class="tags-meta">
            
            <a class="tag-link" href="/tags/Qml/" rel="tag">Qml</a> <a class="tag-link" href="/tags/Qt/" rel="tag">Qt</a> <a class="tag-link" href="/tags/QtQuick/" rel="tag">QtQuick</a> <a class="tag-link" href="/tags/%E7%BB%84%E4%BB%B6%E5%8C%96%E7%BC%96%E7%A8%8B/" rel="tag">组件化编程</a>
            
        </span>
    </span>
    
    
    
    <span class="fa-wrap">
        <i class="fa fa-clock-o"></i>
        <span class="date-meta">
            2019/06/03</span>
    </span>
    
    <span class="fa-wrap">
        <i class="fa fa-eye"></i>
        <span id="busuanzi_value_page_pv"></span>
    </span>
    
    
</div>
        
        
        <p class="fa fa-exclamation-triangle warning">
            本文于<strong>
                1038</strong>
            天之前发表，文中内容可能已经过时。
        </p>
        
    </div>
    
<div id="post-gallery">
    
    <img src="/images/Qml12/1.gif" alt="gallery-img" class="gallery">
    
</div>

    <div class="post-body post-content">
        <ul>
<li><a href="#简介">简介</a></li>
<li><a href="#源码">源码</a></li>
<li><a href="#效果预览">效果预览</a></li>
<li><a href="#qt本身的国际化">Qt本身的国际化</a></li>
<li><a href="#存在翻译不全的问题">存在翻译不全的问题</a></li>
<li><a href="#新的方案">新的方案</a></li>
<li><a href="#关于批量翻译">关于批量翻译</a></li>
<li><a href="#总结">总结</a></li>
</ul>
<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>本文是《玩转Qml》系列文章的第十二篇，主要讨论多国语言动态翻译。</p>
<p>之前分享过使用Qt自带翻译的方案，但是效果不太好。这次分享一个非官方的多国语言方案。</p>
<h2 id="源码"><a href="#源码" class="headerlink" title="源码"></a>源码</h2><p>《玩转Qml》系列文章，配套了一个优秀的开源项目:TaoQuick</p>
<p>github <a href="https://github.com/jaredtao/TaoQuick" target="_blank" rel="noopener">https://github.com/jaredtao/TaoQuick</a></p>
<p>访问不了或者速度太慢，可以用国内的镜像网站gitee</p>
<p><a href="https://gitee.com/jaredtao/TaoQuick" target="_blank" rel="noopener">https://gitee.com/jaredtao/TaoQuick</a></p>
<h2 id="效果预览"><a href="#效果预览" class="headerlink" title="效果预览"></a>效果预览</h2><p>看一下最终效果</p>
<p><img src="/images/Qml12/1.gif" alt="预览"></p>
<p>(原始字符串全部为英文，中文为人工翻译。</p>
<p>其它语言使用的百度翻译api批量翻译，不太准确，暂时先这样)</p>
<h2 id="Qt本身的国际化"><a href="#Qt本身的国际化" class="headerlink" title="Qt本身的国际化"></a>Qt本身的国际化</h2><p>先来回顾一下，Qt的国际化方案：</p>
<ol>
<li><p>C++代码中的字符串使用QObject::tr()包起来，类本身是QObject的子类时可以省略作用域“QObject::”,直接写tr</p>
</li>
<li><p>qml代码中使用qsTr把字符串包起来</p>
</li>
<li><p>pro文件中添加一句TRANSLATIONS += trans_zh.qs ，这个名字起什么无所谓，关键是‘_zh’要有。</p>
</li>
<li><p>调用lrelease工具,扫描项目并生成trans_zh.qs 文件。这个文件是xml格式的，未经过翻译的，需要为这个文件做一些翻译工作。</p>
</li>
<li><p>翻译做好后，调用lupdate工具，生成trans_zh.qm文件。这个文件就是把xml压缩成了二进制。</p>
</li>
<li><p>将qm文件放在运行路径，或者资源文件里。</p>
</li>
<li><p>切换语言时， Qt/C++代码中使用QTranslater加载qm文件，QCoreApplication卸载旧的QTranslater，并安装新的QTranslater。调用<br>QmlEngine::retranslate函数</p>
</li>
</ol>
<p>在5.10以前的版本，Qt是不能直接动态切换语言的，要么重新启动程序，要么把所有的text都set一遍，retranslate是5.10才有的接口。</p>
<h2 id="存在翻译不全的问题"><a href="#存在翻译不全的问题" class="headerlink" title="存在翻译不全的问题"></a>存在翻译不全的问题</h2><p>上面的方案，在<a href="https://github.com/jaredtao/TaoQuick" target="_blank" rel="noopener">TaoQuick</a>中使用了。</p>
<p>明显的问题是，只能翻译静态的内容，动态加载的ListModel，动态切换语言时不能自动刷新。</p>
<p>按照Qt文档所说，Array或者其它数据结构中的内容，也不能自动刷新。</p>
<h2 id="新的方案"><a href="#新的方案" class="headerlink" title="新的方案"></a>新的方案</h2><p>这里抛弃Qt的翻译机制，使用自己实现的方案。</p>
<p>1、约定要用到的字符串，全部用英文。</p>
<p>2、翻译文件使用json文件，一个文件翻译一种语言。</p>
<p>文件命名格式language_xx.json, json内容格式如下；</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="attr">"lang"</span>: <span class="string">"简体中文"</span>,</span><br><span class="line">    <span class="attr">"trans"</span>:[</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="attr">"key"</span>: <span class="string">"Chinese"</span>,</span><br><span class="line">            <span class="attr">"value"</span>: <span class="string">"简体中文"</span></span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="attr">"key"</span>: <span class="string">"Japanese"</span>,</span><br><span class="line">            <span class="attr">"value"</span>: <span class="string">"日语"</span></span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="attr">"key"</span>: <span class="string">"Korean"</span>,</span><br><span class="line">            <span class="attr">"value"</span>: <span class="string">"韩语"</span></span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="attr">"key"</span>: <span class="string">"Menu"</span>,</span><br><span class="line">            <span class="attr">"value"</span>: <span class="string">"菜单"</span></span><br><span class="line">        &#125;,</span><br><span class="line">    ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>其中lang字段表示当前语言，trans字段是所有的翻译项。</p>
<p>3、实现核心翻译器Trans</p>
<p>自己实现一个Trans类，用来加载翻译包、提供翻译数据，类声明如下:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//Trans.h</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">pragma</span> once</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;QObject&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;QHash&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;QList&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;QString&gt;</span></span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Trans</span> :</span> <span class="keyword">public</span> QObject</span><br><span class="line">&#123;</span><br><span class="line">    Q_OBJECT</span><br><span class="line">    <span class="comment">//当前语言</span></span><br><span class="line">    Q_PROPERTY(QString currentLang READ currentLang WRITE setCurrentLang NOTIFY currentLangChanged)</span><br><span class="line">    <span class="comment">//支持的语言列表</span></span><br><span class="line">    Q_PROPERTY(QStringList languages READ languages NOTIFY languagesChanged)</span><br><span class="line">    <span class="comment">//空字符串。用于动态翻译时，通过change信号触发trans</span></span><br><span class="line">    Q_PROPERTY(QString transString READ transString NOTIFY transStringChanged)</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">explicit</span> <span class="title">Trans</span><span class="params">(QObject *parent = <span class="literal">nullptr</span>)</span></span>;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//加载指定文件夹</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">loadFolder</span><span class="params">(<span class="keyword">const</span> QString &amp;folder)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//加载指定文件。成功时返回true，lang参数输出文件代表的语言。</span></span><br><span class="line">    <span class="function"><span class="keyword">bool</span> <span class="title">load</span><span class="params">(QString &amp;lang, <span class="keyword">const</span> QString &amp;filePath)</span></span>;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">const</span> QString &amp;<span class="title">currentLang</span><span class="params">()</span> <span class="keyword">const</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">const</span> QStringList &amp;<span class="title">languages</span><span class="params">()</span> <span class="keyword">const</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">const</span> QString &amp;<span class="title">transString</span><span class="params">()</span> <span class="keyword">const</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> slots:</span><br><span class="line">    <span class="comment">//翻译</span></span><br><span class="line">    <span class="function">QString <span class="title">trans</span><span class="params">(<span class="keyword">const</span> QString &amp;source)</span> <span class="keyword">const</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">setCurrentLang</span><span class="params">(<span class="keyword">const</span> QString &amp;currentLang)</span></span>;</span><br><span class="line">signals:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">currentLangChanged</span><span class="params">(<span class="keyword">const</span> QString &amp;currentLang)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">languagesChanged</span><span class="params">(<span class="keyword">const</span> QStringList &amp;languages)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">transStringChanged</span><span class="params">()</span></span>;</span><br><span class="line"><span class="keyword">protected</span>:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">setLanguages</span><span class="params">(<span class="keyword">const</span> QStringList &amp;languages)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">initEnglish</span><span class="params">()</span></span>;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    QString m_currentLang;</span><br><span class="line">    <span class="comment">// &lt;"English", &lt;"key", "value"&gt;&gt;</span></span><br><span class="line">    QHash&lt;QString, QHash&lt;QString, QString&gt;&gt; m_map;</span><br><span class="line">    QStringList m_languages;</span><br><span class="line">    <span class="comment">//always empty</span></span><br><span class="line">    QString m_transString;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>其中languages是加载过后支持的所有语言，currentLang是当前语言。</p>
<p>trans函数是用来做翻译的，传入要翻译的字符串，根据当前语言，返回翻译后的字符串。</p>
<p>因为软件到处都要翻译，所以trans函数会被频繁调用，使用QHash&lt;QString, QHash&lt;QString, QString&gt;&gt;这样的</p>
<p>嵌套Hash数据结构，保证查询的平均复杂度为O(1).</p>
<p>transString是一个特殊的属性，其值始终为空，在语言被切换时，会触发transStringChange信号。</p>
<p>这样有什么用呢？先知道这个设定，后面qml部分会详细解释。</p>
<p>cpp 实现如下：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//Trans.cpp</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"Trans.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"FileReadWrite.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;QDir&gt;</span></span></span><br><span class="line"><span class="keyword">const</span> <span class="keyword">static</span> <span class="keyword">auto</span> cEnglisthStr = QStringLiteral(<span class="string">"English"</span>);</span><br><span class="line"><span class="keyword">const</span> <span class="keyword">static</span> <span class="keyword">auto</span> cChineseStr = QStringLiteral(<span class="string">"简体中文"</span>);</span><br><span class="line">Trans::Trans(QObject* parent)</span><br><span class="line">    : QObject(parent)</span><br><span class="line">&#123;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> Trans::loadFolder(<span class="keyword">const</span> QString&amp; folder)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="function">QDir <span class="title">dir</span><span class="params">(folder)</span></span>;</span><br><span class="line">    <span class="keyword">auto</span> infos = dir.entryInfoList(&#123; <span class="string">"language_*.json"</span> &#125;, QDir::Files);</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">auto</span> info : infos) &#123;</span><br><span class="line">        QString lang;</span><br><span class="line">        load(lang, info.absoluteFilePath());</span><br><span class="line">    &#125;</span><br><span class="line">    initEnglish();</span><br><span class="line">    <span class="keyword">auto</span> langs = m_map.uniqueKeys();</span><br><span class="line">    <span class="keyword">if</span> (langs.contains(cChineseStr)) &#123;</span><br><span class="line">        langs.removeAll(cChineseStr);</span><br><span class="line">        langs.push_front(cChineseStr);</span><br><span class="line">    &#125;</span><br><span class="line">    setLanguages(langs);</span><br><span class="line">    <span class="keyword">if</span> (m_map.contains(cChineseStr)) &#123;</span><br><span class="line">        setCurrentLang(cChineseStr);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        setCurrentLang(cEnglisthStr);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function">emit <span class="title">transStringChanged</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">bool</span> Trans::load(QString&amp; lang, <span class="keyword">const</span> QString&amp; filePath)</span><br><span class="line">&#123;</span><br><span class="line">    lang.clear();</span><br><span class="line">    QJsonObject rootObj;</span><br><span class="line">    <span class="keyword">if</span> (!TaoCommon::readJsonFile(filePath, rootObj)) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    lang = rootObj.value(<span class="string">"lang"</span>).toString();</span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">auto</span>&amp; trans = rootObj.value(<span class="string">"trans"</span>).toArray();</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">auto</span> i : trans) &#123;</span><br><span class="line">        <span class="keyword">auto</span> transObj = i.toObject();</span><br><span class="line">        QString key = transObj.value(<span class="string">"key"</span>).toString();</span><br><span class="line">        QString value = transObj.value(<span class="string">"value"</span>).toString();</span><br><span class="line">        m_map[lang][key] = value;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> QString &amp;Trans::currentLang() <span class="keyword">const</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">return</span> m_currentLang;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> QStringList &amp;Trans::languages() <span class="keyword">const</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">return</span> m_languages;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> QString &amp;Trans::transString() <span class="keyword">const</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">return</span> m_transString;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> Trans::initEnglish()</span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">if</span> (!m_map.contains(cEnglisthStr)) &#123;</span><br><span class="line">        QHash&lt;QString, QString&gt; <span class="built_in">map</span>;</span><br><span class="line">        <span class="keyword">if</span> (m_map.contains(cChineseStr)) &#123;</span><br><span class="line">            <span class="built_in">map</span> = m_map.value(cChineseStr);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="built_in">map</span> = m_map.value(m_map.keys().first());</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">auto</span> key : <span class="built_in">map</span>.uniqueKeys()) &#123;</span><br><span class="line">            m_map[cEnglisthStr][key] = key;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">QString Trans::trans(<span class="keyword">const</span> QString&amp; source) <span class="keyword">const</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">return</span> m_map.value(m_currentLang).value(source, source);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> Trans::setCurrentLang(<span class="keyword">const</span> QString&amp; currentLang)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">if</span> (m_currentLang == currentLang)</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line">    m_currentLang = currentLang;</span><br><span class="line">    <span class="function">emit <span class="title">currentLangChanged</span><span class="params">(m_currentLang)</span></span>;</span><br><span class="line">    <span class="function">emit <span class="title">transStringChanged</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> Trans::setLanguages(<span class="keyword">const</span> QStringList&amp; languages)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">if</span> (m_languages == languages)</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line">    m_languages = languages;</span><br><span class="line">    <span class="function">emit <span class="title">languagesChanged</span><span class="params">(m_languages)</span></span>;</span><br><span class="line">    <span class="function">emit <span class="title">transStringChanged</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>4、Qml中使用新的翻译语法</p>
<p>qml中的语法如下：</p>
<figure class="highlight qml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">Text</span> &#123;</span><br><span class="line">    <span class="attribute">text</span>: trans.trans(<span class="string">"Welcome"</span>)  + trans.transString</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这是一个很常规的’Qml属性绑定’,或者叫’绑定表达式’, 这样写了以后，text的值依赖于trans.trans()函数返回值和 transString。</p>
<p>当text依赖的属性发出change信号时，qml引擎会重新对这个表达式求值，并把结果赋值给text。</p>
<p>一般情况下，text的值就是trans的返回值，后面的空值不会影响到结果。</p>
<p>当前语言被改变时，函数没有change信号，而transString属性的change信号会被触发，导致qml引擎会重新对这个表达式求值，</p>
<p>此时会重新调用trans函数，按照新的语言返回翻译结果。</p>
<p>Text组件的text属性变化时，会自己刷新UI。</p>
<p>于是，就实现了动态翻译多国语言。</p>
<p>对于ListModel,就把静态字符串换成动态的变量即可：</p>
<figure class="highlight qml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">ListView</span> &#123;</span><br><span class="line">    ...</span><br><span class="line">    <span class="attribute">delegate</span>: <span class="title">Text</span> &#123;</span><br><span class="line">        <span class="attribute">text</span>: trans.trans(modelData)  + trans.transString</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>复杂一些的格式化字符串，也是没有问题的：</p>
<figure class="highlight qml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">Text</span> &#123;</span><br><span class="line">    <span class="attribute">text</span>: trans.trans(<span class="string">"Today is %1, i feel %2"</span>).arg(trans.trans(<span class="string">"Sunday"</span>)).arg(trans.trans(<span class="string">"happy"</span>))  + trans.transString</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>对应的翻译文件：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="attr">"lang"</span>: <span class="string">"简体中文"</span>,</span><br><span class="line">    <span class="attr">"trans"</span>: [</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="attr">"key"</span>: <span class="string">"Today is %1, i feel %2"</span>,</span><br><span class="line">            <span class="attr">"value"</span>: <span class="string">"今天是%1, 我感觉%2"</span></span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="attr">"key"</span>: <span class="string">"Sunday"</span>,</span><br><span class="line">            <span class="attr">"value"</span>: <span class="string">"星期天"</span></span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="attr">"key"</span>: <span class="string">"happy"</span>,</span><br><span class="line">            <span class="attr">"value"</span>: <span class="string">"开心"</span></span><br><span class="line">        &#125;,</span><br><span class="line">        ...</span><br><span class="line">    ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="关于批量翻译"><a href="#关于批量翻译" class="headerlink" title="关于批量翻译"></a>关于批量翻译</h2><p>翻译效果不太理想，不过还是可以分享一下方法。</p>
<p>首先是提取出了所有要翻译的字符串：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">//key.json</span><br><span class="line">[</span><br><span class="line">    <span class="string">"Chinese"</span>,</span><br><span class="line">    <span class="string">"traditional Chinese"</span>,</span><br><span class="line">    <span class="string">"Cantonese"</span>,</span><br><span class="line">    <span class="string">"classical Chinese"</span>,</span><br><span class="line">    <span class="string">"Japanese"</span>,</span><br><span class="line">    <span class="string">"Korean"</span>,</span><br><span class="line">    <span class="string">"French"</span>,</span><br><span class="line">    <span class="string">"Spanish"</span>,</span><br><span class="line">    <span class="string">"Thai"</span>,</span><br><span class="line">    <span class="string">"Arabic"</span>,</span><br><span class="line">    <span class="string">"Russian"</span>,</span><br><span class="line">    <span class="string">"Portuguese"</span>,</span><br><span class="line">    <span class="string">"German"</span>,</span><br><span class="line">    <span class="string">"Italian"</span>,</span><br><span class="line">    <span class="string">"Greek"</span>,</span><br><span class="line">    <span class="string">"Dutch"</span>,</span><br><span class="line">    <span class="string">"Polish"</span>,</span><br><span class="line">    <span class="string">"Bulgarian"</span>,</span><br><span class="line">    <span class="string">"Estonian"</span>,</span><br><span class="line">    <span class="string">"Danish"</span>,</span><br><span class="line">    ...</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<p>其次是写了一个PowerShell脚本，逐个调用百度翻译API，并把结果按照前面的json输出。</p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># trans.ps1</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 需要注册百度翻译的app，获得id和secret</span></span><br><span class="line"></span><br><span class="line"><span class="variable">$baiduId</span> = <span class="string">"xxxxxxxxxx"</span></span><br><span class="line"><span class="variable">$baiduSecret</span> = <span class="string">"xxxxxxxxx"</span></span><br><span class="line"><span class="comment"># 列出百度翻译 支持的语言</span></span><br><span class="line"><span class="variable">$baiduLangs</span> = @&#123;</span><br><span class="line">    zh=<span class="string">"中文"</span>;</span><br><span class="line">    <span class="comment"># cht="繁体中文";</span></span><br><span class="line">    yue=<span class="string">"粤语"</span>;</span><br><span class="line">    wyw=<span class="string">"文言文"</span>;</span><br><span class="line">    jp=<span class="string">"日语"</span>;</span><br><span class="line">    kor=<span class="string">"韩语"</span>;</span><br><span class="line">    fra=<span class="string">"法语"</span>;</span><br><span class="line">    spa=<span class="string">"西班牙语"</span>;</span><br><span class="line">    th=<span class="string">"泰语"</span>;</span><br><span class="line">    ara=<span class="string">"阿拉伯语"</span>;</span><br><span class="line">    ru=<span class="string">"俄语"</span>;</span><br><span class="line">    pt=<span class="string">"葡萄牙语"</span>;</span><br><span class="line">    de=<span class="string">"德语"</span>;</span><br><span class="line">    it=<span class="string">"意大利语"</span>;</span><br><span class="line">    el=<span class="string">"希腊语"</span>;</span><br><span class="line">    nl=<span class="string">"荷兰语"</span>;</span><br><span class="line">    <span class="comment"># pl="波兰语";</span></span><br><span class="line">    bul=<span class="string">"保加利亚语"</span>;</span><br><span class="line">    est=<span class="string">"爱沙尼亚语"</span>;</span><br><span class="line">    dan=<span class="string">"丹麦语"</span>;</span><br><span class="line">    fin=<span class="string">"芬兰语"</span>;</span><br><span class="line">    cs=<span class="string">"捷克语"</span>;</span><br><span class="line">    rom=<span class="string">"罗马尼亚语"</span>;</span><br><span class="line">    <span class="comment"># slo="斯洛文尼亚语";</span></span><br><span class="line">    <span class="comment"># swe="瑞典语";</span></span><br><span class="line">    hu=<span class="string">"匈牙利语"</span>;</span><br><span class="line">    <span class="comment"># vie="越南语";</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment"># 计算MD5</span></span><br><span class="line"><span class="keyword">function</span> getHash([string]<span class="variable">$source</span>) &#123;</span><br><span class="line">    <span class="variable">$stringAsStream</span> = [System.IO.MemoryStream]::new()</span><br><span class="line">    <span class="variable">$writer</span> = [System.IO.StreamWriter]::new(<span class="variable">$stringAsStream</span>)</span><br><span class="line">    <span class="variable">$writer</span>.write(<span class="variable">$source</span>)</span><br><span class="line">    <span class="variable">$writer</span>.Flush()</span><br><span class="line">    <span class="variable">$stringAsStream</span>.Position = <span class="number">0</span></span><br><span class="line">    <span class="variable">$hash</span> = <span class="built_in">Get-FileHash</span> -InputStream <span class="variable">$stringAsStream</span> -algorithm MD5</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> <span class="variable">$hash</span>.Hash.toString().toLower()</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 百度翻译的调用</span></span><br><span class="line"><span class="keyword">function</span> baiduTrans &#123;</span><br><span class="line">    <span class="keyword">param</span>(</span><br><span class="line">        [string]<span class="variable">$q</span>,</span><br><span class="line">        [string]<span class="variable">$from</span> = <span class="string">'en'</span>,</span><br><span class="line">        [string]<span class="variable">$to</span> = <span class="string">'zh'</span></span><br><span class="line">    </span><br><span class="line">    )</span><br><span class="line">    <span class="comment"># 随机盐</span></span><br><span class="line">    <span class="variable">$salt</span> = <span class="built_in">Get-Random</span></span><br><span class="line">    <span class="comment"># token拼接</span></span><br><span class="line">    <span class="variable">$signtoken</span> = <span class="string">"&#123;0&#125;&#123;1&#125;&#123;2&#125;&#123;3&#125;"</span> -f <span class="variable">$baiduId</span>, <span class="variable">$q</span>, <span class="variable">$salt</span>, <span class="variable">$baiduSecret</span></span><br><span class="line">    <span class="comment"># 计算md5</span></span><br><span class="line">    <span class="variable">$signtoken</span> = getHash <span class="variable">$signtoken</span></span><br><span class="line">    <span class="comment"># POST body</span></span><br><span class="line">    <span class="variable">$body</span> = @&#123;</span><br><span class="line">        q     = <span class="variable">$q</span></span><br><span class="line">        from  = <span class="variable">$from</span></span><br><span class="line">        to    = <span class="variable">$to</span></span><br><span class="line">        appid = <span class="variable">$baiduId</span></span><br><span class="line">        salt  = <span class="variable">$salt</span></span><br><span class="line">        sign  = <span class="variable">$signtoken</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="variable">$response</span> = <span class="built_in">Invoke-RestMethod</span> http://api.fanyi.baidu.com/api/trans/vip/translate -Method Post -Body <span class="variable">$body</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">#return $response.dst.toString()</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="literal">$null</span> <span class="nomarkup">-ne</span> <span class="variable">$response</span>.trans_result) &#123;</span><br><span class="line">        <span class="keyword">return</span>  <span class="variable">$response</span>.trans_result[<span class="number">0</span>].dst </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable">$q</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment"># 主函数</span></span><br><span class="line"><span class="keyword">function</span> main() &#123;</span><br><span class="line">    <span class="comment"># 读取keys.json</span></span><br><span class="line">    <span class="variable">$json</span> = <span class="built_in">Get-Content</span> <span class="string">'keys.json'</span> -Encoding  utf8 | <span class="built_in">ConvertFrom-Json</span></span><br><span class="line">    <span class="comment"># 每种语言都翻译一遍</span></span><br><span class="line">    <span class="keyword">foreach</span> (<span class="variable">$lang</span> <span class="keyword">in</span> <span class="variable">$baiduLangs</span>.Keys) &#123;</span><br><span class="line">        <span class="built_in">Write-Host</span> <span class="variable">$lang</span></span><br><span class="line">        <span class="variable">$tlang</span> = <span class="variable">$baiduLangs</span>[<span class="variable">$lang</span>]</span><br><span class="line">        <span class="comment"># 目标语言的名称，默认都用中文表示的。这里将名称翻译成对应的语言。比如：英语 就叫'English'， 日语就用'日本語'</span></span><br><span class="line">        <span class="keyword">if</span> (<span class="variable">$lang</span> <span class="nomarkup">-ne</span> <span class="string">"zh"</span>) &#123;</span><br><span class="line">            <span class="variable">$tlang</span> = baiduTrans <span class="variable">$baiduLangs</span>[<span class="variable">$lang</span>] <span class="string">"zh"</span> <span class="variable">$lang</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment"># 逐条翻译</span></span><br><span class="line">        <span class="variable">$res</span>=@()</span><br><span class="line">        <span class="keyword">foreach</span> (<span class="variable">$key</span> <span class="keyword">in</span> <span class="variable">$json</span>) &#123;</span><br><span class="line">            <span class="built_in">Write-Host</span> <span class="variable">$key</span></span><br><span class="line">            <span class="variable">$dst</span> = baiduTrans <span class="variable">$key</span> <span class="string">"en"</span> <span class="variable">$lang</span></span><br><span class="line">            <span class="variable">$t</span> = @&#123;<span class="string">'key'</span>=<span class="variable">$key</span>; <span class="string">'value'</span>=<span class="variable">$dst</span>&#125;</span><br><span class="line">            <span class="variable">$res</span> +=<span class="variable">$t</span></span><br><span class="line">            <span class="comment"># 延时1秒，毕竟没有充值，被限速了，每秒只能请求1次。</span></span><br><span class="line">            <span class="built_in">Start-Sleep</span> -Seconds <span class="number">1</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment"># 按格式输出</span></span><br><span class="line">        <span class="variable">$obj</span> = @&#123;</span><br><span class="line">            <span class="string">"lang"</span> = <span class="variable">$tlang</span></span><br><span class="line">            <span class="string">"trans"</span> = <span class="variable">$res</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="variable">$targetFileName</span> = <span class="string">"language_&#123;0&#125;.json"</span> -f <span class="variable">$lang</span></span><br><span class="line">        <span class="variable">$obj</span> | <span class="built_in">ConvertTo-Json</span> | <span class="built_in">Set-Content</span> <span class="variable">$targetFileName</span> -Encoding UTF8</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># baiduTrans  "apple" "en" "zh"</span></span><br><span class="line"></span><br><span class="line">main</span><br></pre></td></tr></table></figure>
<p>结果如下，生成了一堆json文件<br><img src="/images/Qml12/2.png" alt=""></p>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>Qml中带个尾巴的写法，虽然有些别扭，但是够用、能达到动态翻译的目标。</p>
<p>如果你有更好的思路，欢迎留言交流。</p>

    </div>
    
    <div class="reward" ontouchstart>
    <div class="reward-wrap">赏
        <div class="reward-box">
            
            <span class="reward-type">
                <img class="alipay" src="/img/zhifubao.jpg"><b>支付宝打赏</b>
            </span>
            
            
            <span class="reward-type">
                <img class="wechat" src="/img/weixin.jpg"><b>微信打赏</b>
            </span>
            
        </div>
    </div>
    <p class="reward-tip">
        为众人抱薪者,不可使其冻毙于霜雪
    </p>
</div>
    
    <div class="post-footer">
        <div>
            
            转载声明：
            文章采用<a href="http://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议</a>进行许可, 转载请注明出处 © <a href="https://jaredtao.github.io" target="_blank">武威的涛哥</a>
            
            
        </div>
        <div>
            
        </div>
    </div>
</article>
<div class="article-nav prev-next-wrap clearfix">
    
    <a href="/2019/06/08/%E7%8E%A9%E8%BD%ACQml(13)-%E5%8A%A8%E7%94%BB%E7%89%B9%E6%95%88-%E9%A3%9E%E5%85%A5/" class="pre-post btn btn-default" title='玩转Qml(13)-动画特效-飞入'>
        <i class="fa fa-angle-left fa-fw"></i><span class="hidden-lg">上一篇</span>
        <span class="hidden-xs">
            玩转Qml(13)-动画特效-飞入</span>
    </a>
    
    
    <a href="/2019/06/02/%E7%8E%A9%E8%BD%ACQml(11)-%E6%9B%B4%E5%BC%BA%E7%9A%84%E6%8B%96%E5%8A%A8%E7%BB%84%E4%BB%B6/" class="next-post btn btn-default" title='玩转Qml(11)-更强的拖动组件'>
        <span class="hidden-lg">下一篇</span>
        <span class="hidden-xs">
            玩转Qml(11)-更强的拖动组件</span><i class="fa fa-angle-right fa-fw"></i>
    </a>
    
</div>

<div id="comments">
    

<div id="vcomments" class="valine"></div>

<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src="/assets/valine.min.js"></script>

<script>
new Valine({
    av: AV,
    el: '#vcomments',
    appId: 'qegD4552u6FU9HoNDvRsonko-gzGzoHsz',
    appKey: 'eitB2FV5n2qyMHcDM7x6EQpt',
    placeholder: '说点什么吧',
    notify: false,
    verify: true,
    avatar: 'mm',
    meta: 'nick,mail'.split(','),
    pageSize: '10',
    path: window.location.pathname,
    lang: 'zh-CN'.toLowerCase()
})
</script>


</div>


                </main>
                
                    <aside id="article-toc" role="navigation" class="col-md-4">
    <div class="widget">
        <h3 class="title">
            文章目录
        </h3>
        
        <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#简介"><span class="toc-text">简介</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#源码"><span class="toc-text">源码</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#效果预览"><span class="toc-text">效果预览</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Qt本身的国际化"><span class="toc-text">Qt本身的国际化</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#存在翻译不全的问题"><span class="toc-text">存在翻译不全的问题</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#新的方案"><span class="toc-text">新的方案</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#关于批量翻译"><span class="toc-text">关于批量翻译</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#总结"><span class="toc-text">总结</span></a></li></ol>
        
    </div>
</aside>
                
            </div>
        </div>
    </section>
    <footer class="main-footer">
    <div class="container">
        <div class="row">
        </div>
    </div>
</footer>
<a id="back-to-top" class="icon-btn hide">
    <i class="fa fa-chevron-up"></i>
</a>
    <div class="copyright">
    <div class="container">
        <div class="row">
            <div class="col-sm-12">
                <div class="busuanzi">
    
    访问量:
    <strong id="busuanzi_value_site_pv">
        <i class="fa fa-spinner fa-spin"></i>
    </strong>
    &nbsp; | &nbsp;
    访客数:
    <strong id="busuanzi_value_site_uv">
        <i class="fa fa-spinner fa-spin"></i>
    </strong>
    
</div>
            </div>
            <div class="col-sm-12">
                <span>Copyright &copy;
                    2019
                    
                </span> |
                <span>
                    Powered by <a href="//hexo.io" class="copyright-links" target="_blank" rel="nofollow">Hexo</a>
                </span> |
                <span>
                    Theme by <a href="//github.com/shenliyang/hexo-theme-snippet.git" class="copyright-links" target="_blank" rel="nofollow">Snippet</a>
                </span>
            </div>
        </div>
    </div>
</div>



<script src="/assets/tagcanvas.min.js?rev=2.9.js"></script>

<script>
var tagOption = {
    textColour: '#444', // 字体颜色
    outlineMethod: 'block', // 选中模式
    outlineColour: '#FFDAB9', // 选中模式的颜色
    interval: 30 || 30, // 动画帧之间的时间间隔，值越大，转动幅度越大
    textHeight: 13,
    outlineRadius: 3,
    freezeActive: true || '', // 选中的标签是否继续滚动
    frontSelect: true || '', // 不选标签云后部的标签
    initial: [0.1, -0.1],
    depth: 0.5,
    decel: 0.95,
    maxSpeed: 0.03,
    reverse: true || '', // 是否反向触发
    fadeIn: 500, // 进入动画时间
    wheelZoom: false || '' // 是否启用鼠标滚轮
}
TagCanvas.Start('tag-cloud-3d', '', tagOption);
</script>


<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>


<script src="/js/app.js?rev=@@hash.js"></script>

</body>
</html>